package br.pucrio.inf.les.SPLAnalyser.impl.squidplugin.sourcecodeanalyser.ast;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

import br.pucrio.inf.les.SPLAnalyser.core.models.impactanalysismodel.Class;
import br.pucrio.inf.les.SPLAnalyser.core.models.impactanalysismodel.Field;
import br.pucrio.inf.les.SPLAnalyser.core.models.impactanalysismodel.ImpactAnalysisModel;
import br.pucrio.inf.les.SPLAnalyser.core.models.util.ImpactAnalysisModelContent;
import br.pucrio.inf.les.genarch.core.project.navigation.ResourceClient;
import br.pucrio.inf.les.genarch.core.project.navigation.visitors.ASTExplorer;
import br.pucrio.inf.les.genarch.core.project.navigation.visitors.ast.SquidTree;

public class JavaASTVisitor implements ResourceClient {

	private ImpactAnalysisModelContent analysisModelContent;
	
	private List<IResource> javaResourceList = new ArrayList<IResource>();
	

	public void visit(IResource resource) {
//		String resourceName = resource.getName();
//		String resourcePhysicalPath = resource.getProjectRelativePath().toString();
		if ( resource.getType() == IResource.FILE ) {
			IFile file = (IFile)resource;
			if ( file.getFileExtension() != null 
					&& file.getFileExtension().equals("java") 
					&& thereIsClassDeclaration(file) ) {	
				javaResourceList.add(resource);
//				Class targetClass = analysisModelContent.findClass(resourceName,classPathTranslator(resourcePhysicalPath, resourceName));
//				ASTree tree = getASTTree(resource);
//				tree.getOrdered(tree.getRoot());
//				
//				
//				List<FieldAccess> fieldAccesses = new ArrayList<FieldAccess>();
//				for(Object o : tree.getOrdered(tree.getRoot())){
//					if(o instanceof FieldAccess){
//						
//						tree.findParent(o);
//						
//						((FieldAccess) o).getExpression().toString();
//						((FieldAccess) o).getName();
//						
//						int u = ASTNode.TYPE_LITERAL;
//						u = ASTNode.TYPE_PARAMETER;
//						u = ASTNode.FIELD_ACCESS;
//						((FieldAccess) o).resolveTypeBinding();
//						((FieldAccess) o).resolveFieldBinding();
//						((FieldAccess) o).resolveTypeBinding();
//						fieldAccesses.add((FieldAccess) o);
//					}
//				}
//				
//				
//				List<FieldDeclaration> fieldDeclarations = new ArrayList<FieldDeclaration>();
//				for(Object o : tree.getOrdered(tree.getRoot())){
//					if(o instanceof FieldDeclaration){
//						((FieldDeclaration) o).getType();
//						((FieldDeclaration) o).fragments();
//						String fieldNameString = "";
//				        List<VariableDeclarationFragment> fragments = ((FieldDeclaration) o).fragments();
//				        if (fragments.size() == 1) {
//				            VariableDeclarationFragment frag = fragments.get(0);
//				            fieldNameString += frag.getName().getFullyQualifiedName();
//				        }
//				        fieldDeclarations.add((FieldDeclaration) o);
//					}
//				}
//				
//				List<ImportDeclaration> importDeclarations = new ArrayList<ImportDeclaration>();
//				for(Object o : tree.getOrdered(tree.getRoot())){
//					if(o instanceof ImportDeclaration){
//						((ImportDeclaration)o).getLocationInParent();
//						((ImportDeclaration)o).getName();
//						((ImportDeclaration)o).toString();
//						importDeclarations.add(((ImportDeclaration)o));
//					}
//				}
//				
//				List<MethodInvocation> methodInvocations = new ArrayList<MethodInvocation>();
//				for(Object o : tree.getOrdered(tree.getRoot())){
//					if(o instanceof MethodInvocation){
//						((MethodInvocation)o).arguments();
//						((MethodInvocation)o).getExpression();
//						((MethodInvocation)o).getLocationInParent();
//						((MethodInvocation)o).getName();
//						((MethodInvocation)o).resolveTypeBinding();
////						((MethodInvocation)o).typeArguments();
//						methodInvocations.add((MethodInvocation)o);
//					}
//				}
				
				
			} 
		}
	}
	
	private boolean thereIsClassDeclaration(IFile file) {		
		ICompilationUnit iCompilationUnit = JavaCore.createCompilationUnitFrom(file);
		
		ASTParser parser = ASTParser.newParser(AST.JLS3); 
		parser.setKind(ASTParser.K_COMPILATION_UNIT);
		parser.setSource(iCompilationUnit); 
		parser.setResolveBindings(false);
		parser.setBindingsRecovery(false);

		CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null);
		
		List types = compilationUnit.types(); 
		
		if(types.isEmpty()) return false;
		else if(types.get(0) instanceof TypeDeclaration){
			return true;	
		} else return false;
	}
	
	
	private SquidTree getASTTree(IResource resource) {
		ASTExplorer astExplorer = null;
		try {
			astExplorer = new ASTExplorer(resource);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		SquidTree tree = astExplorer.getTree();
		
		return tree;
	}
	
	
	public Field getField(Class targetClass, String fieldName){
		for(Field field : targetClass.getDeclaredFields()){
			if(field.getName().equals(fieldName)) return field;
		}
		return null;
	}
	
	public String classPathTranslator(String path, String name){
		String newPath = "";
		newPath = path.replace("src/", "");
		newPath = newPath.replaceAll("(/)",".");
		newPath = newPath.replace("."+name,"");
		return newPath;
		
	}
	public String pathTranslator(String path){
		String newPath = "";
//		newPath = path.replace("src/", "");
//		newPath = newPath.replaceAll("(/)",".");
//		newPath = newPath.replace(".java","");
		return newPath;
//		
	}


	public void setJavaResourceList(List<IResource> javaResourceList) {
		this.javaResourceList = javaResourceList;
	}


	public List<IResource> getJavaResourceList() {
		return javaResourceList;
	}
	
}
